﻿using System;
using System.Collections.Generic;

namespace MvpFramework
{
    /// <summary>
    /// Base class for Presenters
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class Presenter<T> where T : IMvpView
    {
        private readonly T _view;
        private INavigator _navigator;
        private PresenterValidator<T> _presenterValidator;

        //TODO, use ServiceLocator and get rid of this ctor
        protected Presenter(T view)
            : this(view, new Navigator(new CurrentHttpContext(), MvpViewLocationRepository.Instance))
        {
        }

        protected Presenter(T view, INavigator navigator)
        {
            _view = view;
            _navigator = navigator;
        }

        /// <summary>
        /// The Validator for the Presenter
        /// </summary>
        protected virtual PresenterValidator<T> PresenterValidator
        {
            get
            {
                if (_presenterValidator == null)
                {
                    _presenterValidator = new PresenterValidator<T>(this);
                }
                return _presenterValidator;
            }
        }

        /// <summary>
        /// The View this presenter is operating on
        /// </summary>
        protected internal T View
        {
            get { return _view; }
        }

        /// <summary>
        /// Returns true if the <see cref="IValidatedView"/> is Valid.
        /// </summary>
        /// <exception cref="InvalidOperationException">If the View is not an <see cref="IValidatedView"/></exception>
        protected internal bool IsValid
        {
            get { return PresenterValidator.IsValid; }
            set { PresenterValidator.IsValid = value; }
        }

        /// <summary>
        /// Seam to allow mocking of a navigator
        /// </summary>
        /// <param name="navigator"></param>
        public void SetNavigator(INavigator navigator)
        {
            _navigator = navigator;
        }

        /// <summary>
        /// Valdate the View
        /// </summary>
        protected internal void Validate()
        {
            PresenterValidator.Validate();
        }

        /// <summary>
        /// Will navigate to the location specified
        /// </summary>
        /// <param name="location"></param>
        public void NavigateTo(string location)
        {
            _navigator.NavigateTo(location);
        }

        /// <summary>
        /// Will navigate to the View specified
        /// </summary>
        /// <typeparam name="IMvpView"></typeparam>
        public void NavigateTo<IMvpView>()
        {
            _navigator.NavigateTo<IMvpView>();
        }

        /// <summary>
        /// Will navigate to the View specified and send the options
        /// </summary>
        /// <typeparam name="IMvpView"></typeparam>
        /// <param name="options"></param>
        public void NavigateTo<IMvpView>(Dictionary<string, object> options)
        {
            _navigator.NavigateTo<IMvpView>(options);
        }
    }
}